#include "wnd.h"

#include <assert.h>
#include <stdlib.h>

uint32_t g_wnd_id_base = 1000; // ID起始值

int current_max_z = 0; // 组件树最大Z
int current_z = 0;     // 当前激活的Z
STWnd *g_roots[MAX_Z_ORDER] = {NULL};

bool CheckCollision(STRect *rect, STPoint *p, STShapeType shape)
{
    if (shape == SHAPE_RECT) {
        return (p->x >= rect->p.x) && (p->x <= rect->p.x + rect->width) &&
               (p->y >= rect->p.y) && (p->y <= rect->p.y + rect->height);
    } else if (shape == SHAPE_CIRCLE) {
        uint32_t dx = p->x - (rect->p.x + rect->width / 2);
        uint32_t dy = p->y - (rect->p.y + rect->height / 2);
        return (dx * dx + dy * dy) <= (rect->width / 2) * (rect->width / 2);
    }
    return false;
}

// 例如，如果有两个重叠的子窗口，先添加的A，后添加的B。在原来的处理顺序中，B作为最后一个子节点，会被先处理，因此如果点击在重叠区域，B会先处理事件。而修改后的顺序，先处理A，再处理B，此时如果A处理了事件，B就不会收到事件，这可能不符合期望，因为B在视觉上位于A之上，应该优先处理。
static bool HandleEventCapture(STWnd *wnd, STKeyEvent ev)
{
    // 先处理当前窗口
    if (CheckCollision(&wnd->rect, &ev.point, wnd->shapeType)) {
        if (wnd->vApi->OnEvent(wnd, ev)) {
            return true; // 事件被当前窗口消费
        }
    }

    // 顺序遍历子节点（从第一个子节点开始，沿next向后遍历）
    STWnd *child = wnd->firstChild;
    while (child != NULL) {
        if (HandleEventCapture(child, ev)) {
            return true; // 事件被子节点消费
        }
        child = child->next;
    }

    return false; // 事件未被消费
}
// 辅助函数，递归处理窗口及其子节点
static bool HandleEventBubble(STWnd *wnd, STKeyEvent ev)
{
    // 逆序遍历子节点，从最后一个子节点开始，沿着pre指针向前遍历
    STWnd *child = wnd->lastChild;
    while (child != NULL) {
        if (HandleEventBubble(child, ev)) {
            return true;
        }
        child = child->pre;
    }

    // 处理当前窗口
    if (CheckCollision(&wnd->rect, &ev.point, wnd->shapeType)) {
        if (wnd->vApi->OnEvent(wnd, ev)) {
            return true;
        }
    }
    return false;
}

static void WndDispatchEvent(STKeyEvent ev)
{
    bool isCaptureEvent = (ev.type == E_MODAL_EVENT); // 示例条件
    // 从最高z_order开始遍历
    for (int z = current_max_z; z >= 0; z--) {
        STWnd *root = g_roots[z];
        if (!root)
            continue;

        bool handled = isCaptureEvent ? HandleEventCapture(root, ev) : HandleEventBubble(root, ev);

        if (handled)
            return;
    }
}

static void WndSetState(STWnd *wnd, uint32_t flags)
{
    if (!wnd)
        return;
    DEBUG_LOG("id: %d, flag", wnd->id, flags);
    uint32_t old = wnd->state;
    wnd->state |= flags;
    if (wnd->state != old && wnd->OnStateChanged) {
        wnd->OnStateChanged(wnd, old);
    }
}

static void WndClearState(STWnd *wnd, uint32_t flags)
{
    if (!wnd)
        return;
    DEBUG_LOG("id: %d, flag", wnd->id, flags);
    uint32_t old = wnd->state;
    wnd->state &= ~flags;
    if (wnd->state != old && wnd->OnStateChanged) {
        wnd->OnStateChanged(wnd, old);
    }
}

static bool WndHasState(STWnd *wnd, uint32_t flags)
{
    DEBUG_LOG("id: %d, flag", wnd->id, flags);
    return wnd && (wnd->state & flags) == flags;
}

/*
WndRemoveFromParent() 未触发任何回调（如销毁通知），可能导致资源泄漏（若子节点需额外清理）。
修复建议：
在移除前后添加回调（如 OnDetach）。
*/
void WndRemoveFromParent(STWnd *child)
{
    if (!child || !child->parent)
        return;
    STWnd *parent = child->parent;

    if (child->pre)
        child->pre->next = child->next;
    else
        parent->firstChild = child->next;

    if (child->next)
        child->next->pre = child->pre;
    else
        parent->lastChild = child->pre;

    child->parent = NULL;
    child->pre = NULL;
    child->next = NULL;
}

static WndResult WndAddChild(STWnd *parent, STWnd *child)
{
    if (!parent || !child)
        return WND_ERR_NULL_PTR;
    DEBUG_LOG("pid: %d, id: %d", parent->id, child->id);

    if (child->parent == parent)
        return WND_ERR_ALREADY_CHILD;

    // 检测循环引用
    STWnd *ancestor = parent;
    while (ancestor) {
        if (ancestor == child)
            return WND_ERR_CYCLE;
        ancestor = ancestor->parent;
    }

    // 移除旧关联：WndRemoveFromParent(child) 会清除 child 与原父节点的所有指针关联（parent、pre、next），确保它是一个“孤立”节点。
    // 建立新关联：随后将其安全添加到新父节点的子链表末尾，避免新旧父节点的状态冲突。
    // 确保数据一致性
    WndRemoveFromParent(child);

    child->parent = parent;
    child->driver = parent->driver;
    if (!parent->firstChild) {
        parent->firstChild = child;
        parent->lastChild = child;
    } else {
        parent->lastChild->next = child;
        child->pre = parent->lastChild;
        parent->lastChild = child;
    }
    return WND_OK;
}

static STWnd *WndFindByIdRecursive(STWnd *wnd, uint32_t target_id)
{
    if (!wnd)
        return NULL;

    // 当前节点匹配
    if (wnd->id == target_id) {
        return wnd;
    }

    // 深度优先遍历子节点
    STWnd *child = wnd->firstChild;
    while (child) {
        STWnd *found = WndFindByIdRecursive(child, target_id);
        if (found)
            return found;
        child = child->next;
    }
    return NULL;
}

static WndResult WndFindById(STWnd *root, uint32_t target_id, STWnd **result)
{
    if (!root || !result)
        return WND_ERR_NULL_PTR;
    DEBUG_LOG("root_id: %d, tid: %d", root->id, target_id);

    *result = WndFindByIdRecursive(root, target_id);
    return *result ? WND_OK : WND_ERR_NOT_FOUND;
}

static void WndTraverse(STWnd *root, WndCallback callback)
{
    if (!root || !callback)
        return;
    DEBUG_LOG("id: %d, cb: %p", root->id, callback);
    // 递归处理子节点
    STWnd *child = root->firstChild;
    while (child) {
        STWnd *next = child->next;
        WndTraverse(child, callback);
        child = next;
    }
    // 处理当前节点
    callback(root);
}

static STWnd *WndCreateWndEx(size_t size, EMWndType type, const STWndVApi *vApi)
{
    STWnd *wnd = (STWnd *)calloc(1, size);
    if (!wnd)
        return NULL;

    // 自动生成ID（原子操作保证线程安全）
    wnd->id = __sync_fetch_and_add(&g_wnd_id_base, 1);
    wnd->type = type;
    wnd->vApi = vApi;

    if (vApi->OnInit) {
        vApi->OnInit(wnd);
    }
    return wnd;
}

// 订阅窗口事件
static void WndSubscribeEvent(STWnd *wnd, EventType event, EventCallback callback, void *userdata)
{
    if (!wnd || !callback)
        return;

    // 创建订阅节点
    EventSubscription *sub = (EventSubscription *)malloc(sizeof(EventSubscription));
    sub->event = event;
    sub->callback = callback;
    sub->userdata = userdata;
    sub->next = NULL;

    // 添加到链表头部
    sub->next = wnd->eventSubscriptions;
    wnd->eventSubscriptions = sub;
}

// 取消订阅（通过回调函数和userdata匹配）
static void WndUnsubscribeEvent(STWnd *wnd, EventType event, EventCallback callback, void *userdata)
{
    if (!wnd || !callback)
        return;

    EventSubscription **curr = &wnd->eventSubscriptions;
    while (*curr) {
        EventSubscription *entry = *curr;
        if (entry->event == event && entry->callback == callback && entry->userdata == userdata) {
            *curr = entry->next; // 绕过当前节点
            free(entry);
            break;
        } else {
            curr = &entry->next;
        }
    }
}

// 触发窗口事件（如点击、按键）
static void WndTriggerEvent(STWnd *wnd, EventType event)
{
    if (!wnd)
        return;

    // 遍历订阅链表，调用匹配的回调
    EventSubscription *sub = wnd->eventSubscriptions;
    while (sub) {
        if (sub->event == event) {
            sub->callback(wnd, event, sub->userdata);
        }
        sub = sub->next;
    }

    // 可选：事件冒泡到父节点
    // if (wnd->parent) WndTriggerEvent(wnd->parent, event);
}

static void DestroyCallback(STWnd *wnd)
{
    const STWndVApi *vtbl = wnd->vApi;
    if (vtbl && vtbl->OnDestroy) {
        vtbl->OnDestroy(wnd);
    }

    // 清理事件订阅链表
    EventSubscription *sub = wnd->eventSubscriptions;
    while (sub) {
        EventSubscription *next = sub->next;
        free(sub);
        sub = next;
    }
    wnd->eventSubscriptions = NULL;

    free(wnd);
}

static void RenderCallback(STWnd *wnd)
{
    const STWndVApi *vtbl = wnd->vApi;
    if (vtbl && vtbl->OnPaint) {
        vtbl->OnPaint(wnd);
    }
}

// 后序遍历销毁专用
static void WndDestroyTraverse(STWnd *root, WndCallback callback)
{
    if (!root || !callback)
        return;

    // 先处理子节点
    STWnd *child = root->firstChild;
    while (child) {
        STWnd *next = child->next;
        WndDestroyTraverse(child, callback);
        child = next;
    }

    // 最后处理当前节点
    callback(root);
}

static void WndRenderTree(STWnd *root)
{
    WndTraverse(root, RenderCallback);
}

static void WndDestroyTree(STWnd *root)
{
    WndDestroyTraverse(root, DestroyCallback);
}

static void WndSetRect(STWnd *wnd, STRect rect)
{
    if (wnd) {
        wnd->rect = rect;
    }
}

const STWndApi g_wndApi = {
    .SetState = WndSetState,
    .ClearState = WndClearState,
    .HasState = WndHasState,
    .AddChild = WndAddChild,
    .FindById = WndFindById,
    .Traverse = WndTraverse,
    .RemoveFromParent = WndRemoveFromParent,
    .CreateWndEx = WndCreateWndEx,
    .SubscribeEvent = WndSubscribeEvent,
    .UnsubscribeEvent = WndUnsubscribeEvent,
    .TriggerEvent = WndTriggerEvent,
    .RenderTree = WndRenderTree,
    .DestroyTree = WndDestroyTree,
    .DispatchEvent = WndDispatchEvent,
    .SetRect = WndSetRect
};

void Wnd_OnInit(STWnd *wnd)
{
    DEBUG_LOG("Wnd_OnInit");
}

void Wnd_OnDestroy(STWnd *wnd)
{
    DEBUG_LOG("Wnd_OnDestroy");
}

void Wnd_OnPaint(STWnd *wnd)
{
    DEBUG_LOG("Wnd_OnPaint");
}

bool Wnd_OnEvent(STWnd *wnd, STKeyEvent ev)
{
    return false;
}

STWnd *CreateWnd()
{
    static const STWndVApi wndVtbl = {
        .OnInit = Wnd_OnInit,
        .OnDestroy = Wnd_OnDestroy,
        .OnPaint = Wnd_OnPaint,
        .OnEvent = Wnd_OnEvent};
    return WndCreateWndEx(sizeof(STWnd), WND_TYPE_BASE, &wndVtbl);
}
